home *** CD-ROM | disk | FTP | other *** search
/ Network CD 2 / Network CD - Volume 2.iso / programs / internet / tcp / mail / amitcp_ups10.lha / orig / upsd.c < prev   
Encoding:
C/C++ Source or Header  |  1993-10-03  |  7.9 KB  |  374 lines

  1. #ifndef lint
  2. static char RCSid[] = "$Header: upsd.c,v 1.4 86/11/19 15:21:52 scooter Exp $";
  3. #endif
  4.  
  5. /*
  6.  * upsd - package delivery server
  7.  *
  8.  * upsd is the program that is called by inetd when a ups
  9.  * request is issued.  It will read and write to standard input
  10.  * and standard output.  Here is a description of the ups
  11.  * protocol:
  12.  *
  13.  *     ups            upsd                    type
  14.  *
  15.  *  user_name    ------>        login name of package receiver        String
  16.  *  from_name    ------>        login name of package sender        String
  17.  *  full_name    ------>        full name of package sender        String
  18.  *  message    ------>        mail message to send            String
  19.  *        <-----        0 for OK                Byte
  20.  * For each file:
  21.  *  file_name    ------>        name of file to be delivered        String
  22.  *  file_size    ------>        size of file in bytes            Long
  23.  *        <-----        0 for OK                Byte
  24.  *  file    ------>        file size bytes
  25.  *        <-----        0 for OK                Byte
  26.  *  file_mode    ------>        file mode                Int
  27.  *        <-----        0 for OK                Byte
  28.  *
  29.  * When its all done:
  30.  *  complete    ------>        We're done ('-Done-')            String
  31.  *        <-----        0 for OK                Byte
  32.  *
  33.  * $Author: scooter $
  34.  * $Revision: 1.4 $
  35.  * $Date: 86/11/19 15:21:52 $
  36.  *
  37.  * $Log:    upsd.c,v $
  38.  * Revision 1.4  86/11/19  15:21:52  scooter
  39.  * Changed error severity level from ERR to INFO
  40.  * 
  41.  * Revision 1.3  86/09/19  18:53:37  scooter
  42.  * Added -i option for mail specification.
  43.  * Also added syslog stuff.
  44.  * 
  45.  * Revision 1.2  85/08/21  22:28:11  scooter
  46.  * Release revision: added more complete RCS headers.
  47.  * 
  48.  *
  49.  */
  50.  
  51. #include    <stdio.h>
  52. #include    <pwd.h>
  53. #include    <grp.h>
  54. #include    <sys/file.h>
  55. #include    <sys/types.h>
  56. #include    <netinet/in.h>
  57. #include    <netdb.h>
  58. #include    <syslog.h>
  59. #include    <string.h>
  60.  
  61. long    atol();
  62. int    atoi();
  63.  
  64. char    buffer[BUFSIZ*5];    /* character input buffer */
  65. char    file_name[BUFSIZ];    /* file name */
  66. char    file_path[BUFSIZ];    /* full path to destination */
  67. char    user_name[BUFSIZ];    /* Receiver name */
  68. char    from_name[BUFSIZ];    /* Sender name */
  69. char    full_name[BUFSIZ];    /* Full name of sender */
  70. char    file_list[BUFSIZ];    /* List of all files */
  71. long    file_size;        /* number of bytes in file */
  72. int    file_mode;        /* mode of the file */
  73. char    mail_message[BUFSIZ*4];    /* mail message */
  74. int    mcount;            /* number of characters in mail buffer */
  75.  
  76. int    fid;            /* File descriptor for destination */
  77. #ifdef DEBUG
  78. int    debugflag = 1;        /* Debug flag */
  79. #else
  80. int    debugflag = 0;        /* Debug flag */
  81. #endif
  82.  
  83. main(argc, argv)
  84. int argc;
  85. char **argv;
  86. {
  87.     char *ptr,*tptr,*mptr;
  88.     int f, i, file;
  89.     struct sockaddr_in sin;
  90.     struct hostent *peer;
  91.     struct passwd *pwent;
  92.  
  93.     openlog("upsd",LOG_ODELAY,LOG_DAEMON);
  94.  
  95.     syslog(LOG_DEBUG, "started - test");
  96.  
  97.     if(argc>1 && !strcmp(argv[1], "-d") )
  98.         debugflag++;
  99.  
  100.     if (debugflag)
  101.         syslog(LOG_DEBUG,"started");
  102.  
  103.     i = sizeof (sin);
  104.     if (getpeername(0, &sin, &i) < 0)
  105.         syslog(LOG_ERR,"getpeername failed: %m");
  106.  
  107.     if (debugflag)
  108.         syslog(LOG_DEBUG,"Calling gethostbyaddr");
  109.  
  110.     peer = gethostbyaddr((char *)&sin.sin_addr,
  111.         sizeof(sin.sin_addr),sin.sin_family);
  112.  
  113.     buffer[0] = '\0';
  114.     file_list[0] = '\0';
  115.  
  116.     if (debugflag)
  117.         syslog(LOG_DEBUG,"Reading first buffer");
  118.  
  119.     read(0, buffer, BUFSIZ*5);  /* fetch receiver and sender names */
  120.  
  121.     if (debugflag)
  122.         syslog(LOG_DEBUG,"receiver/sender/message: %s",buffer);
  123.  
  124.     ptr = buffer;
  125.     while (*ptr != '\n')
  126.         ptr++;
  127.     *ptr++ = NULL;
  128.     strcpy(user_name, buffer);    /* save receiver name */
  129.     tptr = ptr;
  130.     while (*tptr != '\n')
  131.         tptr++;
  132.     *tptr++ = NULL;
  133.     strcpy(from_name, ptr);        /* save sender name */
  134.     mptr = tptr;
  135.     while ((*mptr != '\n') && (*mptr != '\0'))
  136.         mptr++;
  137.     *mptr++ = NULL;
  138.     strcpy (full_name, tptr);    /* save sender's full name */
  139.     strcpy (mail_message, mptr);    /* save the mail message */
  140.  
  141.     /*
  142.      * Check for a valid user
  143.      */
  144.     if ((pwent = getpwnam(user_name)))
  145.         ack();
  146.     else
  147.     {
  148.         error("Receiver name","No such person");
  149.         exit(1);
  150.     }
  151.  
  152.     mcount = strlen (mail_message);
  153.     if (debugflag)
  154.         syslog(LOG_DEBUG,"mail message (%d chars):\n %s", mcount, mail_message);
  155.  
  156.     for (file = 0 ;;)
  157.     {
  158.         if (read(0, buffer, BUFSIZ) <= 0) {
  159.             error("file name","premature EOF or file read error");
  160.             continue;
  161.         }
  162.         strcpy(file_name,buffer);
  163.  
  164.         if (debugflag)
  165.             syslog(LOG_DEBUG,"File name:%s",file_name);
  166.  
  167.  
  168.         /*
  169.          * Are we done??
  170.          */
  171.         if (!strncmp(file_name,"-Done-",6)) break;
  172.  
  173.         if ( (fid = opendest(user_name,file_name,
  174.             pwent->pw_uid,pwent->pw_gid)) <= 0 )
  175.         {
  176.             continue;
  177.         }
  178.         ack();
  179.  
  180.         if (read(0, buffer, BUFSIZ) <= 0) {
  181.             error("file size","premature EOF or file read error");
  182.             continue;
  183.         }
  184.  
  185.         file_size = atol(buffer); /* get number of bytes */
  186.         ack();
  187.  
  188.         copyfile(&file);
  189.  
  190.         if (read(0, buffer, BUFSIZ) <= 0) {
  191.             error("file mode","premature EOF or file read error");
  192.             continue;
  193.         }
  194.         file_mode = atoi(buffer);     /* get the file mode */
  195.         file_mode &= 0700;        /* Strip the low order modes */
  196.         if (chmod(file_path,file_mode)) {
  197.             error("file mode","chmod failed");
  198.             continue;
  199.         }
  200.         
  201.         ack();
  202.         chown(file_path,pwent->pw_uid,pwent->pw_gid);
  203.  
  204.     }
  205.     ack();
  206.  
  207.     if (file)
  208.         sendmail(from_name,full_name,peer->h_name,
  209.             user_name,file_list,file++,mail_message,mcount);
  210. }
  211.  
  212. /*
  213. copyfile
  214. copyfile will copy file_size many bytes from stdin to a temporarily created
  215. file. The filename will be passed back via buffer.
  216. */
  217.  
  218. copyfile(file)
  219. int *file;
  220. {
  221.     long cnt;                /* file size counter */
  222.     int i;
  223.  
  224.     cnt = file_size;        /* count down input bytes */
  225.     while (cnt > 0) {
  226.         i = read(0, buffer, BUFSIZ);
  227.         write(fid, buffer, i);
  228.         cnt -= i;
  229.     }
  230.     close(fid);
  231.  
  232.     ack();
  233.     sprintf(buffer,"%-15s",file_name);
  234.     if (*file%4)
  235.         strcat(file_list," ");
  236.     else
  237.         strcat(file_list,"\n\t");
  238.  
  239.     (*file)++;
  240.     strcat(file_list,buffer);
  241. }
  242.  
  243. /*
  244. error(option, string)
  245. char *option, *string;
  246. This routine is called when some error condition has been encountered.
  247. option contains an identifier message, while string contains the actual
  248. error message. Before message is printed, a non-null character is output
  249. first, then the string error message.
  250. */
  251.  
  252. error(option, string)
  253. char *option, *string;
  254. {
  255.     char buf[BUFSIZ];
  256.  
  257.  
  258.     buf[0] = 1;
  259.     write(1, buf, 1);    /* nak */
  260.     sprintf(buf, "upsd: %s: %s\n", option, string);
  261.     write(1, buf, strlen(buf)+1);
  262.  
  263.     syslog(LOG_INFO,"error - %s",buf);
  264. }
  265.  
  266.  
  267.  
  268. /*
  269.  * ack()
  270.  * This routine is called to return an OK to the remote host.
  271.  */
  272.  
  273. ack()
  274. {
  275.     buffer[0] = 0;
  276.     write(1,buffer,1);
  277. }
  278.  
  279.  
  280.  
  281. /*
  282.  * opendest(name,file)
  283.  * char *name,*file;
  284.  *
  285.  * Open the destination file "file" in UPSDIR/user, creating the
  286.  * file if necessary.
  287.  */
  288.  
  289. int
  290. opendest(name,file,uid,gid)
  291. char *name,*file;
  292. int uid,gid;
  293. {
  294.     int ret;
  295.  
  296.     sprintf(file_path,"%s/%s",UPSDIR,name); /* Form path to directory */
  297.  
  298.     if (access(file_path,F_OK) == (-1))
  299.     {
  300.         mkdir(file_path,0700);
  301.         chown(file_path,uid,gid);
  302.     }
  303.  
  304.     sprintf(file_path,"%s/%s/%s",UPSDIR,name,file);
  305.  
  306.     if (!access(file_path,F_OK))
  307.     {
  308.         error("file creation","A file by that name has already been sent to that user.");
  309.         return(0);
  310.     } else {
  311.         ret = open(file_path,O_WRONLY|O_CREAT,0600);
  312.         if (ret <= 0)
  313.         {
  314.             sprintf(buffer,"unable to open destination file: %s",
  315.                 file_path);
  316.             error("file open",buffer);
  317.             return(0);
  318.         }
  319.         return(ret);
  320.     }
  321. }
  322.  
  323.  
  324.  
  325. /*
  326.  * sendmail(from,full,from_host,to,list,mess,count)
  327.  * char *from,*full,*to,*from_host,*list,*mess;
  328.  * int    count;
  329.  *
  330.  * This routine sends mail to the destination user to inform
  331.  * them that ups files are awaiting them.
  332.  */
  333.  
  334. sendmail(from,full,from_host,to,list,file,mess,count)
  335. char *from,*full,*to,*from_host,*list,*mess;
  336. int file,count;
  337. {
  338.     FILE *send,*popen();
  339.     static char myhost[BUFSIZ];
  340.  
  341.     gethostname(myhost,BUFSIZ);
  342.     sprintf(buffer,"%s -f%s@%s -F\"%s\" -t",SENDMAIL,from,from_host,full);
  343.  
  344.     if(debugflag)
  345.         syslog(LOG_DEBUG,"sendmail\n%s",buffer);
  346.  
  347.     send = popen(buffer,"w");
  348.  
  349.     fprintf(send,"To: %s@%s\n",to,myhost);
  350.  
  351.     if(debugflag)
  352.         syslog(LOG_DEBUG,"To: %s@%s",to,myhost);
  353.  
  354.     fprintf(send,"Subject: UPS delivery\n");
  355.     if (file > 1)
  356.         strcpy(buffer,"files");
  357.     else
  358.         strcpy(buffer,"file");
  359.  
  360.     fprintf(send,"I have sent you the following %s using ups:\n",buffer);
  361.     fprintf(send,"%s\n\n",list);
  362.     if (file > 1)
  363.         strcpy(buffer,"these files");
  364.     else
  365.         strcpy(buffer,"this file");
  366.  
  367.     fprintf(send,"To retrieve %s, use the ups command.\n\n\n",buffer);
  368.     if (count)
  369.         fprintf(send,"%s\n",mess);
  370.     else
  371.         fprintf(send,"\n\n\n\n---ups\n");
  372.     pclose(send);
  373. }
  374.